home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
sweep10.zip
/
SWEEP.DOC
< prev
next >
Wrap
Text File
|
1991-04-03
|
23KB
|
611 lines
Sweep Memory Management Library
Copyright (c) 1990-1991 Eric Tauck
All Rights Reserved
Eric Tauck
1304 Deerpass Road
Marengo, IL 60152
U.S.A
Compuserve: 72457,1557
Internet: 72457.1557@compuserve.com
The Sweep Library is a library of routines for managing memory
and maintaining a heap. The advantage of the Sweep Library over
the heap routines built into Turbo Pascal or Turbo C is that the
Sweep Library never suffers from memory fragmentation. The Sweep
Library is ideal for applications that repeatedly allocate,
deallocate, and resize blocks of memory.
The Sweep Library is available for Turbo C and Turbo Pascal. The
Turbo C version should work with all versions of Turbo C and all
memory models except tiny. The Turbo C version may also work
with other compilers that support standard LIB files and Pascal
calling conventions. The Turbo Pascal version SWEEP5.TPU was
compiled with Turbo Pascal version 5.5 and should work with Turbo
Pascal versions 5.0 and 5.5, SWEEP6.TPU was compiled with Turbo
Pascal version 6. You should rename the unit that matches your
version of Turbo Pascal to SWEEP.TPU.
This library may be freely used and distributed. The most recent
version of the Sweep Library, including the Turbo Assembler
source code, may be acquired on 5.25" or 3.5" disk by sending $20
to the address above. The source code is for personal use only
and may not be distributed. Refer to the end of this document
for a version history of the Sweep Library.
DISCLAIMER OF WARRANTY
THIS SOFTWARE AND MANUAL ARE DISTRIBUTED "AS IS" AND WITHOUT
WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR ANY OTHER
WARRANTIES WHETHER EXPRESSED OR IMPLIED. BECAUSE OF THE VARIOUS
HARDWARE AND SOFTWARE ENVIRONMENTS INTO WHICH THIS PROGRAM MAY BE
PUT, NO WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE IS OFFERED.
GOOD DATA PROCESSING PROCEDURE DICTATES THAT ANY PROGRAM BE
THOROUGHLY TESTED WITH NON-CRITICAL DATA BEFORE RELYING ON IT.
THE USER MUST ASSUME THE ENTIRE RISK OF USING THE PROGRAM. ANY
LIABILITY OF THE SELLER WILL BE LIMITED EXCLUSIVELY TO PRODUCT
REPLACEMENT OR REFUND OF PURCHASE PRICE.
Sweep Library Description
-------------------------
The necessary files for Turbo C are:
SWEEP.LIB
SWEEP.H
The Sweep Library routines are included in a Turbo C program by
using the #include statement and linking the library file with
your compiled program:
#include "sweep.h"
and compile as:
tcc myprog sweep.lib
The only file necessary for Turbo Pascal is:
SWEEP.TPU
The Sweep Library routines are included in a Turbo Pascal program
by using the USES statement:
USES Sweep;
A heap is created with the HeapInit or HeapInitBlk routines.
These routines require the address and size of a memory block in
which to create the heap. The farcoreleft and farmalloc in Turbo
C provide ideal functions for allocating a block of memory for
the heap:
/* Turbo C */
#include "sweep.h"
void far *base; /* 'far' only for small/medium mdls */
unsigned long size;
size = farcoreleft(); /* bytes available */
base = farmalloc (size); /* allocate memory */
HeapInit (base, size); /* create heap */
Though you could use the MaxAvail and GetMem routines in Turbo
Pascal, you would be limited to a heap of 64K (because GetMem
will not allocate blocks larger than 64K). This limitation can
be overcome by using three special Turbo Pascal routines provided
in the Sweep unit: DosAvail, DosAlloc, and DosFree. These func-
tions allocate memory directly from the operating system rather
than the Turbo Pascal heap manager and are not restricted to 64K.
Since the Turbo Pascal heap manager usually takes all available
memory, you must use the $M directive to make some memory avail-
able:
{ Turbo Pascal }
{$M 16384,0,0} { tell TP not to use any extra mem. }
USES Sweep; { remember: rename SWEEP5.TPU or SWEEP6.TPU }
VAR
base: Pointer;
size: LongInt;
BEGIN
size := DosAvail; { bytes available }
base := DosAlloc (size); { allocate memory }
HeapInit (base, size); { create heap }
Once the heap has been created, you can allocate memory with
HeapAlloc and release memory with HeapFree. HeapAlloc does not
return an address to the allocated memory, but rather a 16-bit
handle. This handle type is called HeapHandle and is used by all
the heap management routines. Memory blocks are accessed by
retrieving their address with HeapAddr and assigning this address
to a pointer:
/* Turbo C */
/* create an array and zero all elements */
/* the fars are only needed for small or medium models */
typedef int ArrayType [1000];
HeapHandle MyArrayPtr;
ArrayType far *MyArray;
int i;
MyArrayPtr = HeapAlloc (sizeof (ArrayType));
MyArray = (ArrayType far *) HeapAddr(MyArrayPtr);
for (i = 0; i < 1000; i++) (*MyArray)[i] = 0;
{ Turbo Pascal }
{ create an array and zero all elements }
TYPE
ArrayType = ARRAY [1..1000] OF Integer;
VAR
MyArrayPtr: HeapHandle;
MyArray: ^ArrayType;
i: Integer;
BEGIN
MyArrayPtr := HeapAlloc (SizeOf (ArrayType));
MyArray := HeapAddr (MyArrayPtr);
FOR i := 1 TO 1000 DO MyArray^[i] := 0;
You can use HeapResult or the value of the handle returned by
HeapAlloc and HeapResize to check for errors. The error handle
in C is called SWEEP_NULL and in Pascal it's called SWEEP_NIL.
The value of SWEEP_NULL and SWEEP_NIL is zero, so in C you can
use the value of the handle as a conditional expression:
/* Turbo C */
HeapHandle h;
h = HeapAlloc (10); /* allocate 10 bytes */
if (!h) /* if not allocated */
printf ("Allocation Error"); /* print error message */
When a memory block is allocated or resized, the address of other
blocks may change. This is a result of maintaining an unfrag-
mented heap. The address of a block returned by HeapAddr is only
valid until the next time the heap is manipulated.
A limitation of the Sweep Library heap routines is that there is
fixed number of blocks that can be allocated. HeapInit sets the
maximum number of blocks to about 1/64 of the available memory
space. The maximum number of blocks can be explicitly defined
with HeapInitBlk.
The size of the heap can be changed with HeapShrink, HeapExpand,
and HeapReloc. HeapShrink shrinks the heap by using less space
at the end of the heap. HeapExpand enlarges the heap by using
more space at the end of the heap. HeapReloc changes the base
address of an existing heap. The following example creates a
10000 byte heap and then increases its size by 100 bytes:
/* Turbo C */
void far *base;
unsigned long size;
size = 10000;
base = farmalloc (size);
HeapInit (base, size); /* create 10000 byte heap */
base = farrealloc (base,size+100); /* increase by 100 bytes */
HeapReloc (base); /* relocate heap */
HeapExpand (100); /* expand heap */
The HeapReloc is necessary in the example above because the C
function farrealloc may change address of the memory block being
reallocated.
You can use the Sweep Library pointer manipulation routines to
access data structures greater than 64K in Turbo Pascal. If you
calculate the 32 bit offset of an element within a large data
structure, you can add the offset to the base address with the
PointerAdd function, for instance:
{ Turbo Pascal }
{ create array of 50000 integers and zero all elements }
CONST
MyArrayDim = 50000;
MyArrayElem = SizeOf (Integer);
VAR
MyArrayPtr: HeapHandle;
IntPtr: ^Integer;
i: Word;
BEGIN
MyArrayPtr := HeapAlloc (MyArrayDim * MyArrayElem);
FOR i := 1 TO 1000 DO
BEGIN
IntPtr := PointerAdd (HeapAddr (MyArrayPtr),
LongInt(i - 1) * LongInt (MyArrayElem));
IntPtr^ := 0;
END;
You can use the same technique to access large data structures in
Turbo C.
Sweep Routine Summary
---------------------
PointerNormal normalize a pointer
PointerDenormal denormalize a pointer
PointerAdd add an offset to a pointer
PointerSub subtract an offset from a pointer
PointerValue convert a pointer to a linear value
PointerDiff calculate the difference between two pointers
CopyBlock copy a memory block
CopyForward forward copy a memory block
CopyBackward reverse copy a memory block
HeapInit initialize a heap
HeapInitBlk initialize a heap with a block count
HeapCurrent return the current heap address
HeapSelect switch to a new heap
HeapMemory return the bytes available
HeapBlocks return the blocks available
HeapShrink reduce the size of a heap
HeapExpand increase the size of a heap
HeapReloc relocate the heap
HeapAlloc allocate a memory block
HeapResize resize a memory block
HeapFree free a memory block
HeapSize return the size of a memory block
HeapAddr return the address of a memory block
HeapResult return the error code of the last operation
DosAvail return available system memory (Turbo Pascal)
DosAlloc allocate system memory (Turbo Pascal)
DosFree free system memory (Turbo Pascal)
Sweep Routine Descriptions
--------------------------
Though all the pointer values accepted and returned by the Turbo
C functions are listed as type 'far', all of the routines except
PointerDenormal (which always returns a far pointer) will also
work with huge pointers. A 'far' modifier for pointer variables
is only necessary when using the small or medium memory models.
A 'huge' or 'near' modifier is never necessary.
Many of the Turbo C routines return a value when the Turbo Pascal
equivalents don't. Ignore any return value descriptions for
Turbo Pascal PROCEDURE types.
CopyBackward
- void far* CopyBackward (void far *d, void far *s,
unsigned long c)
- PROCEDURE CopyBackward (d, s: Pointer; c: LongInt)
Copy a contiguous block of memory. The block may be greater
than 64K bytes. The copy operation is started from the end of
the block, so an overlapping copy will only work if the desti-
nation is at a higher address than the source. The destination
address is returned. If the source and destination do not
overlap, this function has the same effect as CopyForward.
CopyBlock
- void far* CopyBlock (void far *d, void far *s,
unsigned long c)
- PROCEDURE CopyBlock (d, s: Pointer; c: LongInt)
Copy a contiguous block of memory. The block may be greater
than 64K bytes. The destination address is returned. This
function works with all overlapping blocks (unlike CopyBackward
or CopyForward).
CopyForward
- void far * CopyForward (void far *d, void far *s,
unsigned long c)
- PROCEDURE CopyForward (d, s: Pointer; c: LongInt)
Copy a contiguous block of memory. The block may be greater
than 64K bytes. The copy operation is started from the begin-
ning of the block, so an overlapping copy will only work if the
destination is at a lower address than the source. The desti-
nation address is returned. If the source and destination do
not overlap, this function has the same effect as CopyBackward.
DosAlloc
- FUNCTION DosAlloc (s: LongInt): Pointer;
Allocate system memory. Memory must be made available using
the $M directive. For instance {$M 16000,4000,4000} allocates
16000 bytes for the stack and 4000 bytes for the Turbo Pascal
heap. All remaining system memory may be allocated by DosAl-
loc. This function is only available in Turbo Pascal.
DosAvail
- FUNCTION DosAvail: LongInt;
Return available system memory. Use this function find the
largest block available for DosAlloc. This function is only
available in Turbo Pascal.
DosFree
- PROCEDURE DosFree (p: Pointer);
Free allocated system memory. Use this function to release
memory allocated with DosAlloc. This function is only avail-
able in Turbo Pascal.
PointerAdd
- void far * PointerAdd (void far *p, unsigned long o)
- FUNCTION PointerAdd (p: Pointer; o: LongInt): Pointer;
Add an offset to a far pointer. The resulting address is
normalized.
PointerDenormal
- void far * PointerDenormal (void far *p)
- FUNCTION PointerDenormal (p: Pointer): Pointer;
Denormalize a far pointer. As much of the segment of an ad-
dress as possible is transferred to the offset. This function
does the opposite of PointerNormal. The result is always a far
pointer, even when using the huge memory model.
PointerDiff
- unsigned long PointerDiff (void far *p1, void far *p2)
- FUNCTION PointerDiff (p1, p2: Pointer): LongInt;
Calculate the difference between two far pointers. The result
is a standard 32 bit signed value (not a pointer).
PointerNormal
- void far * PointerNormal (void far *p)
- FUNCTION PointerNormal (p: Pointer): Pointer;
Normalize a far pointer. As much of the offset of an address
as possible is transferred to the segment. This function does
the opposite of PointerDenormal.
PointerSub
- void far * PointerSub (void far *p, unsigned long o)
- FUNCTION PointerSub (p: Pointer; o: LongInt): Pointer;
Subtract an offset from a far pointer. The resulting address
is normalized.
PointerValue
- unsigned long PointerValue (void far *p)
- FUNCTION PointerValue (p: Pointer): LongInt;
Return the 32 bit linear value equivalent of a far pointer.
This function is used to calculate the difference between two
far pointers.
HeapAddr
- void far * HeapAddr (HeapHandle b)
- FUNCTION HeapAddr (b: HeapHandle): Pointer;
Return the address of a heap memory block.
HeapAlloc
- HeapHandle HeapAlloc (unsigned long s)
- FUNCTION HeapAlloc (s: LongInt): HeapHandle;
Allocate a memory block from the heap. Return the block handle
or SWEEP_NULL (Turbo C) or SWEEP_NIL (Turbo Pascal) if error.
's' is the number of bytes to allocate.
HeapBlocks
- unsigned HeapBlocks (void)
- FUNCTION HeapBlocks: Word;
Return the number of available memory blocks in the heap.
HeapCurrent
- void far * HeapCurrent (void)
- FUNCTION HeapCurrent: Pointer;
Return the address of the current heap.
HeapExpand
- void far * HeapExpand (unsigned long s)
- PROCEDURE HeapExpand (s: LongInt)
Increase the size of the current heap. The heap is expanded at
its end by 's' bytes. The current heap address is returned.
Note: You are responsible for making sure that there is enough
available memory to perform this operation.
HeapFree
- void HeapFree (HeapHandle b)
- PROCEDURE HeapFree (b: HeapHandle)
Free a heap memory block.
HeapInit
- void far * HeapInit (void far *h, unsigned long s)
- PROCEDURE HeapInit (h: Pointer; s: LongInt)
Initialize a heap at the given address. The minimum heap size
is 12 bytes. The maximum number of blocks is calculated as the
heap size divided by 64 with a minimum of 32 and a maximum of
about 21800. The newly initialized heap becomes the current
heap and the original heap address is returned. The function
HeapInitBlk is identical except that the maximum number of
memory blocks is specified by the user rather than being calcu-
lated. 'h' is the base heap address and 's' is the number of
bytes allocated to the heap.
HeapInitBlk
- void far * HeapInitBlk (void far *h, unsigned long s,
unsigned b)
- PROCEDURE HeapInitBlk (h: Pointer; s: LongInt; b: Word)
Initialize a heap at the given address. The minimum heap size
is 12 bytes. The maximum number of blocks may be adjusted down,
so use HeapBlocks to find the actual number initialized. The
newly initialized heap becomes the current heap and the origi-
nal heap address is returned. The function HeapInit is identi-
cal except that the maximum number of blocks is calculated
rather than being specified by the user. 'h' is the base heap
address, 's' is the number of bytes allocated to the heap, and
'b' is the number of blocks to assign to the heap.
HeapMemory
- unsigned long HeapMemory (void)
- FUNCTION HeapMemory: LongInt;
Return the total available bytes in the heap.
HeapReloc
- void far * HeapReloc (void far *h);
- PROCEDURE HeapReloc (h: Pointer);
Relocate the heap. The current heap block addresses are
changed to reflect the new base address 'h'. This function is
used if the heap is moved to a new location, though it doesn't
actually move the heap. HeapReloc is useful when resizing the
memory block containing the heap or reading a saved heap into
memory.
HeapResize
- HeapHandle HeapResize (HeapHandle b, unsigned long s)
- PROCEDURE HeapResize (b: HeapHandle; s: LongInt)
Resize a heap memory block. Returns the block handle (un-
changed) or SWEEP_NULL if error.
HeapResult
- int HeapResult (void)
- FUNCTION HeapResult: Word;
Return the error code of the last heap operation (or zero if no
error). The error code is reset with each operation (including
this one). An error code of 1 is out of memory and 2 is out of
memory blocks. The symbolic constants SWEEP_NOERROR,
SWEEP_OUTOFBLOCKS, and SWEEP_OUTOFMEMORY have been defined to
check for these return values.
HeapSelect
- void far * HeapSelect (void far *h)
- PROCEDURE HeapSelect (h: Pointer)
Switch to a previously initialized heap. Returns the current
heap address.
HeapShrink
- void far * HeapShrink (unsigned long s)
- PROCEDURE HeapShrink (s: LongInt)
Decrease the size of the heap. The heap is adjusted at its end
by 's' bytes. The current heap address is returned. Note: the
heap MUST have at least 's' bytes free.
HeapSize
- unsigned long HeapSize (HeapHandle b)
- FUNCTION HeapSize (b: HeapHandle): LongInt;
Return the size of a heap memory block.
Version History
---------------
Version Description
------- -----------
1.00 Initial release.
1.10 HeapReloc and CopyBlock functions added. HeapShrink
and HeapExpand now return the heap address (C versions
only). The value of SWEEP_NULL and SWEEP_NIL, returned
by a HeapAlloc and HeapResize failure, is now zero.
This allows the handle to be used in a C conditional
statement (zero indicates failure, non-zero indicates
success). This library version is also slightly fast-
er, primarily in memory copying.